home *** CD-ROM | disk | FTP | other *** search
/ Ultimedia 2 / Ultimedia 2.iso / tools / soundtools / speechtoy / source.lha / SpeechToy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-14  |  49.4 KB  |  1,438 lines

  1. /* !!! To those who haven't figured it out yet:
  2.  * !!! set stack to 15000 before compiling.
  3.  * !!! This is a generally good thing to do if
  4.  * !!! the compiler blows up on a large source.
  5.  * !!! if your program suddenly KILLS the compiler,
  6.  * !!! increase stack by 5K and try again. jeeze you guys.
  7.  */
  8. /* This program was written to show the use of gadgets in a
  9.  * window. Thus one menu, one auto requester, but lots of
  10.  * gadget types.
  11.  * For the sake of example, two mutual exclude gadgets
  12.  * (female/male) are shown that perform a function that might
  13.  * be better implemented as a toggle image, in a manner similar
  14.  * to that shown in the inflection Mode gadget.
  15.  * Again for the sake of example, the proportional gadgets
  16.  * are generated dynamicly (that is, copied from a template and
  17.  * filled in), whereas most gadgets are declared staticly in
  18.  * the struct declaration, which saves the initialization code
  19.  * space.
  20.  * Lastly, for the sake of example, this program is extremely
  21.  * verbose in the way of comments. Hope you don't mind.
  22.  */
  23. /* Written by David M Lucas. */
  24. /* If you find somthing you don't like, fix it! Have fun! */
  25. /* Send complaints to /dev/null. really. */
  26. /* Thanks Amiga. */
  27.  
  28. /* 00001 940406 Mike Haas - changed old LIBRARY_VERSION to LIBRARY_MINIMUM
  29.  * 00002   ""   Mike Haas - mp_SigTask is no longer (Task*), but (void*)
  30.  * 00003   ""   Mike Haas - fixed bad FaceWindow nil references
  31.  * 00004   ""   Mike Haas - adjust for 1.3/2.0 incompatibility bug in C=
  32.  *                          include devices/narrator.h  (In 2.0, they
  33.  *                          changed size of narrator_rb structure, which
  34.  *                          made mouth_rb structure incompatible between
  35.  *                          the 2 versions.  I implement a VERY ugly
  36.  *                          workaround here, so this works in both OS's!)
  37.  */
  38.  
  39. #include "exec/types.h"
  40. #include "exec/exec.h"
  41. #include "intuition/intuition.h"
  42. #include "intuition/intuitionbase.h"
  43. #include "graphics/regions.h"
  44. #include "graphics/copper.h"
  45. #include "graphics/gels.h"
  46. #include "graphics/gfxbase.h"
  47. #include "devices/keymap.h"
  48. #include "hardware/blit.h"
  49. #include "devices/narrator.h"
  50. #include "libraries/translator.h"
  51.  
  52. /* #define DEBUG */
  53.  
  54. /*00004 - part of workaround for 1.3/2.0 incompatibility*/
  55. USHORT  NarratorVersion;
  56.  
  57. #define CONTWINDW 321 /* Overall Control Window Width/Height */
  58. #define CONTWINDH 123
  59. #define FACEWINDW 32  /* Overall Face Window Width / Height */
  60. #define FACEWINDH 44  /* this includes borders, incedently */
  61.  
  62. /* Pen numbers to draw gadget borders/images/text with */
  63. #define REDP   3        /* color in register 3 once was red */
  64. #define BLKP   2        /* color in register 2 was black */
  65. #define WHTP   1        /* color in register 1 was white */
  66. #define BLUP   0        /* color in register 0 was blue */
  67.  
  68. /* the length of the English and phonetic buffers */
  69. #define ESTRINGSIZE 512
  70. #define PSTRINGSIZE 768 /* phonemes are longer than english */
  71.  
  72. #define NUMPROPS 4      /* number of proportional gadgets */
  73.  
  74. /* Ranges of proportional data */
  75. #define RNGFREQ  (MAXFREQ  - MINFREQ)  +1
  76. #define RNGRATE  (MAXRATE  - MINRATE)  +1
  77. #define RNGPITCH (MAXPITCH - MINPITCH) +1
  78. #define RNGVOL   (MAXVOL   - MINVOL)   +1
  79.  
  80. struct TextAttr TestFont = /* Needed for opening screen */
  81.    {
  82.    (STRPTR)"topaz.font",
  83.    TOPAZ_EIGHTY, 0, 0
  84.    };
  85.  
  86. /* Which audio channels to use */
  87. BYTE audio_chan[] = {3, 5, 10, 12};
  88. /* Pointer to translator library vectors */
  89. struct Library *TranslatorBase = 0;
  90. struct MsgPort talk_port; /* Message port for the say's I/O  */
  91. struct MsgPort read_port; /* Message port for the say's I/O  */
  92. struct mouth_rb mouth_io;  /* IO Request block, mouth flavor */
  93. /* IO Request block, narrator flavor */
  94. struct narrator_rb voice_io;
  95. /* indicative of the Open return */
  96. UBYTE NarratorOpenError = -1;        /* not yet opened */
  97. /* indicative of a Translations success */
  98. UBYTE TranslatorError = 0;
  99. USHORT i;
  100.  
  101. /* These are used to draw the eyes and mouth size relative */
  102. USHORT MouthWMult;
  103. USHORT EyesLeft;
  104. USHORT MouthHMult;
  105. USHORT EyesTop;
  106. USHORT EyesBottom;
  107. USHORT YMouthCenter;  /* Pixels from top edge */
  108. USHORT XMouthCenter;  /* Pixels from left edge */
  109. USHORT yaw;
  110. USHORT LipWidth, LipHeight;
  111.  
  112. /* String Gadgets *********************************************
  113.  * First the string gadgets.
  114.  * 1) because the Phonetic string is refreshed programaticly
  115.  * (that is, deleted and added again) quite often, and doing
  116.  * this requires the use of RefreshGadgets(), and this causes
  117.  * gadgets that are closer to the beginning of the list than
  118.  * the gadget given to RefreshGadgets() to flicker.
  119.  * 2) because they don't flicker when OTHER gadgets
  120.  * (ie female/male, coming up) are deleted and added.
  121.  */
  122. /* These'll be used to put a nice double line border around
  123.  * each of the two string gadgets.
  124.  */
  125. /* y,x pairs drawn as a connected line. Be sure to have an even
  126.  * number of arguments (ie complete pairs).
  127.  */
  128.  
  129. USHORT StrVectors[] = {
  130.    0, 0,   297, 0,   297, 14,   0, 14,
  131.    0, 1,   296, 1,   296, 13,   1, 13,
  132.    1, 1
  133. };
  134. struct Border StrBorder = {
  135.    -4, -3,           /* initial offsets, gadget relative */
  136.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  137.    9,                /* number of vectors */
  138.    StrVectors,     /* pointer to the actual array of vectors */
  139.    NULL       /* no next Border, can point to another border */
  140. };
  141.  
  142. /* The same undo buffer is used for both string gadgets,
  143.  * this is sized to largest so that largest fits.
  144.  */
  145. UBYTE UndoBuffer[PSTRINGSIZE];
  146.  
  147. /* English String Gadget is where the user types in English */
  148. /* default text */
  149. UBYTE EnglBuffer[ESTRINGSIZE] = "This is amiga speaking.";
  150. struct StringInfo EnglInfo = {
  151.    EnglBuffer,    /* pointer to I/O buffer */
  152.    UndoBuffer,    /* pointer to undo buffer */
  153.    0,             /* buffer position */
  154.    ESTRINGSIZE,   /* max number of chars, including NULL */
  155.    0, 0,          /* first char in display, undo positions */
  156.    24,          /* number of chars (currently) in the buffer */
  157.    0, 0, 0,    /* position variables calculated by Intuition */
  158.    NULL,          /* no pointer to RastPort */
  159.    0,             /* not a LongInt string gadget */
  160.    NULL           /* no pointer to alternate keymap */
  161. };
  162. struct IntuiText EnglText = {
  163.    WHTP, BLUP,    /* FrontPen, BackPen */
  164.    JAM1,          /* DrawMode */
  165.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  166.    &TestFont,     /* pointer to TextFont */
  167.    "English:",    /* pointer to Text */
  168.    NULL           /* no pointer to NextText */
  169. };
  170. struct Gadget EnglStrGadget = {
  171.    NULL,             /* pointer to Next Gadget */
  172.    11, 63, 290, 10,  /* (Left Top Width Height) Hit Box */
  173.    GADGHCOMP,        /* Flags */
  174.    RELVERIFY,        /* Activation flags */
  175.    STRGADGET,        /* Type */
  176.    (APTR)&StrBorder, /* pointer to Border Image */
  177.    NULL,             /* no pointer to SelectRender */
  178.    &EnglText,        /* pointer to GadgetText */
  179.    0,                /* no MutualExclude */
  180.    (APTR)&EnglInfo,  /* pointer to SpecialInfo */
  181.    0,                /* no ID */
  182.    NULL              /* no pointer to special data */
  183. };
  184.  
  185. /* Phonetic string gadget is where the program puts the
  186.  * translated string, necessating a call to RefreshGadgets(),
  187.  * and is where the user can type in Phonemes.
  188.  */
  189. UBYTE PhonBuffer[PSTRINGSIZE] =
  190.   "DHIHS IHZ AHMIY3GAH SPIY4KIHNX.";
  191. struct StringInfo PhonInfo = {
  192.    PhonBuffer,    /* pointer to input buffer */
  193.    UndoBuffer,    /* pointer to undo buffer */
  194.    0,             /* initial buffer position */
  195.    PSTRINGSIZE,   /* max number of chars, including NULL */
  196.    0, 0,          /* display, undo positions */
  197.    32,          /* number of chars (currently) in the buffer */
  198.    0, 0, 0,    /* position variables calculated by Intuition */
  199.    NULL,          /* no pointer to RastPort */
  200.    NULL,          /* not a LongInt string gadget */
  201.    NULL           /* no pointer to alternate keymap */
  202. };
  203. struct IntuiText PhonText = {
  204.    WHTP, BLUP,    /* FrontPen, BackPen */
  205.    JAM1,          /* DrawMode */
  206.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  207.    &TestFont,     /* pointer to TextFont */
  208.    "Phonetics:",  /* pointer to Text */
  209.    NULL           /* no pointer to NextText */
  210. };
  211. struct Gadget PhonStrGadget = {
  212.    &EnglStrGadget,   /* pointer to Next Gadget */
  213.    11, 94, 290, 10,  /* (Left Top Width Height) Hit Box */
  214.    GADGHCOMP,        /* Flags */
  215.    RELVERIFY,        /* Activation flags */
  216.    STRGADGET,        /* Type */
  217.    (APTR)&StrBorder, /* pointer to Border Image */
  218.    NULL,             /* no pointer to SelectRender */
  219.    &PhonText,        /* pointer to GadgetText */
  220.    0,                /* no MutualExclude */
  221.    (APTR)&PhonInfo,  /* pointer to SpecialInfo */
  222.    0,                /* no ID */
  223.    NULL              /* no pointer to special data */
  224. };
  225.  
  226. /* Now come the Boolean Gadgets.
  227.  * The female/male pair shows the simplest implementation I
  228.  * could think of to show how you can do mutual-exclude type
  229.  * things yourself. They are two toggle gadgets that use
  230.  * highlight image. The program starts with one selected, and
  231.  * then if either of them are hit, both toggle. Gadgets must
  232.  * be deleted and added whenever you want to change structure
  233.  * member values that intuition expects to be coming from the
  234.  * user, not a program (like the SELECTED bit in flags). Note
  235.  * that certain structure values CAN be changed programaticly
  236.  * without all this broohaha. Haha. Consult the intuition
  237.  * manual.
  238.  */
  239. /* Female Toggle (Highlight Image)
  240.    (Quasi mutual exclude with Male Toggle) */
  241. struct Image FemaleImage = {
  242.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  243.    20, 10, 1,  /* Width, Height, Depth */
  244.    NULL,       /* pointer to ImageData */
  245.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  246. };
  247. struct Gadget FemaleGadget = {
  248.    &PhonStrGadget,      /* pointer to Next Gadget */
  249.    134, 34, 20, 10,     /* (Left Top Width Height) Hit Box */
  250.    GADGIMAGE | GADGHCOMP,  /* Flags */
  251.    /* Activation flags */
  252.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  253.    BOOLGADGET,          /* Type */
  254.    (APTR)&FemaleImage,  /* pointer to GadgetRender */
  255.    NULL,                /* no pointer to SelectRender */
  256.    NULL,                /* no pointer to GadgetText */
  257.    0,                   /* no MutualExclude */
  258.    NULL,                /* no pointer to SpecialInfo */
  259.    0,                   /* no ID */
  260.    NULL                 /* no pointer to special data */
  261. };
  262.  
  263. /* Male Toggle (Highlight Image)
  264.    (Quasi mutual Exclude with above) */
  265. struct Image MaleImage = {
  266.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  267.    20, 10, 1,  /* Width, Height, Depth */
  268.    NULL,       /* pointer to ImageData */
  269.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  270. };
  271. struct Gadget MaleGadget = {
  272.    &FemaleGadget,    /* pointer to Next Gadget */
  273.    154, 34, 20, 10,  /* (Left Top Width Height) Hit Box */
  274.    GADGIMAGE | GADGHCOMP | SELECTED,   /* Flags */
  275.    /* Activation flags */
  276.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT | ACTIVATE,
  277.    BOOLGADGET,       /* Type */
  278.    (APTR)&MaleImage, /* pointer to GadgetRender */
  279.    NULL,             /* no pointer to SelectRender */
  280.    NULL,             /* no pointer to GadgetText */
  281.    0,                /* no MutualExclude */
  282.    NULL,             /* no pointer to SpecialInfo */
  283.    0,                /* no ID */
  284.    NULL              /* no pointer to special data */
  285. };
  286.  
  287. /* This boolean toggle gadget has an
  288.  * alternate image that indicates
  289.  * selection. The image stays flipped
  290.  * until it gets another hit. (it toggles)
  291.  */
  292. /* Inflection Mode Toggle (AltImage) *************************/
  293. struct Image HumanImage = {
  294.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  295.    40, 20, 1,  /* Width, Height, Depth */
  296.    NULL,       /* pointer to ImageData */
  297.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  298. };
  299. struct Image RobotImage = {
  300.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  301.    40, 20, 1,  /* Width, Height, Depth */
  302.    NULL,       /* pointer to ImageData */
  303.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  304. };
  305. struct Gadget ModeGadget = {
  306.    &MaleGadget,            /* pointer to Next Gadget */
  307.    134, 2, 40, 20,        /* (Left Top Width Height) Hit Box */
  308.    GADGIMAGE | GADGHIMAGE, /* Flags */
  309.    /* Activation flags */
  310.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  311.    BOOLGADGET,             /* Type */
  312.    (APTR)&HumanImage,      /* pointer to GadgetRender */
  313.    (APTR)&RobotImage,      /* pointer to SelectRender */
  314.    NULL,                   /* no pointer to GadgetText */
  315.    0,                      /* no MutualExclude */
  316.    NULL,                   /* no pointer to SpecialInfo */
  317.    0,                      /* no ID */
  318.    NULL                    /* no pointer to special data */
  319. };
  320.  
  321. /* Face Toggle (image and text) ******************************/
  322. struct IntuiText FaceIText = {
  323.    WHTP, BLUP, /* FrontPen, BackPen */
  324.    JAM2,       /* DrawMode */
  325.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  326.    &TestFont,  /* pointer to TextFont */
  327.    "Face",/* pointer to Text */
  328.    NULL        /* no pointer to NextText */
  329. };
  330. struct Image FaceImage = {
  331.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  332.    40, 10, 1,  /* Width, Height, Depth */
  333.    NULL,       /* pointer to ImageData */
  334.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  335. };
  336. struct Gadget FaceGadget = {
  337.    &ModeGadget,            /* pointer to Next Gadget */
  338.    134, 23, 40, 10,       /* (Left Top Width Height) Hit Box */
  339.    GADGIMAGE | GADGHCOMP,  /* Flags */
  340.    /* Activation flags */
  341.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  342.    BOOLGADGET,             /* Type */
  343.    (APTR) &FaceImage,      /* pointer to GadgetRender */
  344.    NULL,                   /* no pointer to SelectRender */
  345.    &FaceIText,             /* pointer to GadgetText */
  346.    0,                      /* no MutualExclude */
  347.    NULL,                   /* no pointer to SpecialInfo */
  348.    0,                      /* no ID */
  349.    NULL                    /* no pointer to special data */
  350. };
  351.  
  352. /* Stop Hit (image and text) ******************************/
  353. struct IntuiText StopIText = {
  354.    WHTP, BLUP, /* FrontPen, BackPen */
  355.    JAM2,       /* DrawMode */
  356.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  357.    &TestFont,  /* pointer to TextFont */
  358.    "Stop",/* pointer to Text */
  359.    NULL        /* no pointer to NextText */
  360. };
  361. struct Image StopImage = {
  362.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  363.    40, 10, 1,  /* Width, Height, Depth */
  364.    NULL,       /* pointer to ImageData */
  365.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  366. };
  367. struct Gadget StopGadget = {
  368.    &FaceGadget,            /* pointer to Next Gadget */
  369.    134, 45, 40, 10,        /* Left Top Width Height Hit Box */
  370.    GADGIMAGE | GADGHCOMP,  /* Flags */
  371.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  372.    BOOLGADGET,             /* Type */
  373.    (APTR) &StopImage,      /* pointer to GadgetRender */
  374.    NULL,                   /* no pointer to SelectRender */
  375.    &StopIText,             /* pointer to GadgetText */
  376.    0,                      /* no MutualExclude */
  377.    NULL,                   /* no pointer to SpecialInfo */
  378.    0,                      /* no ID */
  379.    NULL                    /* no pointer to special data */
  380. };
  381.  
  382. /* This is a hit (as opposed to toggle)
  383.    gadget that starts the translation.*/
  384. /* Translate Hit (Highlight image) ***************************/
  385. USHORT TransVectors[] = {
  386.    0, 0,    79, 0,    79, 13,   0, 13,
  387.    0, 1,    78, 1,    78, 12,   1, 12,
  388.    1, 1
  389. };
  390. struct Border TransBorder = {
  391.    -4, -3,           /* initial offsets, gadget relative */
  392.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  393.    9,                /* number of vectors */
  394.    TransVectors,     /* pointer to the array of vectors */
  395.    NULL              /* no next Border, can point to another */
  396. };
  397. struct IntuiText TranslateIText = {
  398.    WHTP, BLUP, /* FrontPen, BackPen */
  399.    JAM2,       /* DrawMode */
  400.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  401.    &TestFont,  /* pointer to TextFont */
  402.    "Translate",/* pointer to Text */
  403.    NULL        /* no pointer to NextText */
  404. };
  405. struct Gadget TranslateGadget = {
  406.    &StopGadget,      /* pointer to Next Gadget */
  407.    229, 48, 71, 8,   /* (Left Top Width Height) Hit Box */
  408.    GADGHCOMP,        /* Flags */
  409.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  410.    BOOLGADGET,       /* Type */
  411.    (APTR)&TransBorder,  /* no pointer to GadgetRender */
  412.    NULL,             /* no pointer to SelectRender */
  413.    &TranslateIText,  /* pointer to GadgetText */
  414.    0,                /* no MutualExclude */
  415.    NULL,             /* no pointer to SpecialInfo */
  416.    0,                /* no ID */
  417.    NULL              /* no pointer to special data */
  418. };
  419.  
  420. /* This is a hit (as opposed to toggle) Starts the narration */
  421. /* Speak Hit (Highlight Image) *******************************/
  422. USHORT SpeakVectors[] = {
  423.    0, 0,    47, 0,    47, 13,   0, 13,
  424.    0, 1,    46, 1,    46, 12,   1, 12,
  425.    1, 1
  426. };
  427. struct Border SpeakBorder = {
  428.    -4, -3,           /* initial offsets, gadget relative */
  429.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  430.    9,                /* number of vectors */
  431.    SpeakVectors,   /* pointer to the actual array of vectors */
  432.    NULL       /* no next Border, can point to another border */
  433. };
  434. struct IntuiText SpeakIText = {
  435.    WHTP, BLUP, /* FrontPen, BackPen */
  436.    JAM2,       /* DrawMode */
  437.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  438.    &TestFont,  /* pointer to TextFont */
  439.    "Speak",    /* pointer to Text */
  440.    NULL        /* no pointer to NextText */
  441. };
  442. struct Gadget SpeakGadget = {
  443.    &TranslateGadget, /* pointer to Next Gadget */
  444.    261, 79, 40, 8,   /* (Left Top Width Height) Hit Box */
  445.    GADGHCOMP,        /* Flags */
  446.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  447.    BOOLGADGET,       /* Type */
  448.    (APTR)&SpeakBorder,  /* pointer to GadgetRender */
  449.    NULL,             /* no pointer to SelectRender */
  450.    &SpeakIText,      /* pointer to GadgetText */
  451.    0,                /* no MutualExclude */
  452.    NULL,             /* no pointer to SpecialInfo */
  453.    0,                /* no ID */
  454.    NULL              /* no pointer to special data */
  455. };
  456.  
  457. /* Now the proportional gadgets. */
  458. /* Proportional Gadgets **************************************/
  459. /* The following variables are used to create proportional
  460.  * Gadgets. These variables will be filled in with copies of
  461.  * the generic Gadgetry below.
  462.  */
  463. SHORT PropCount = 0;       /* index to next available Gadget */
  464. struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
  465. /* dummy AUTOKNOB Images are required */
  466. struct Image PImages[NUMPROPS];
  467. /* These get copies of TPropInfo */
  468. struct PropInfo PInfos[NUMPROPS];
  469. /* These get copies of TPropGadget */
  470. struct Gadget Props[NUMPROPS];
  471. struct IntuiText TPropText = {
  472.    WHTP, BLUP,   /* FrontPen, BackPen */
  473.    JAM1,         /* DrawMode */
  474.    0, -10,       /* LeftEdge, TopEdge (relative to gadget) */
  475.    &TestFont,    /* pointer to TextFont */
  476.    NULL,         /* pointer to Text is filled at runtime */
  477.    NULL          /* no pointer to NextText */
  478. };   
  479. struct PropInfo TPropInfo = {
  480.    AUTOKNOB | FREEHORIZ,  /* Flags */
  481.    0, 0,            /* Pots:  Horiz, Vert: both start at 0 */
  482.    0x1FFF, 0x1FFF,  /* Bodies: Horiz is 1/8, Vert is 1/8 */
  483.    0, 0, 0, 0, 0, 0 /* System usage stuff */
  484. };
  485. /* this is the template for the Gadget of a horizontal */
  486. /* Proportional Gadget */
  487. struct Gadget TPropGadget = {
  488.    &SpeakGadget,              /* pointer to NextGadget */
  489.    7, 12, 115, 10,            /* Select Box L T W H */
  490.    GADGHCOMP | GADGIMAGE,     /* Flags */
  491.    GADGIMMEDIATE | RELVERIFY, /* Activation flags */
  492.    PROPGADGET,                /* Type */
  493.    NULL,       /* pointer to Image filled in later */
  494.    NULL,       /* no pointer to SelectRender */
  495.    NULL,       /* no pointer to GadgetText */
  496.    0,          /* no MutualExclude */
  497.    NULL,       /* SpecialInfo proportional data filled later */
  498.    0,          /* no ID */
  499.    NULL        /* no pointer to special data */
  500. };
  501.  
  502. struct IntuitionBase *IntuitionBase = 0;
  503. struct GfxBase *GfxBase = 0;
  504.  
  505. /* Only one menu. */
  506.  
  507. ULONG MenuNumber;
  508. ULONG TheMenu;
  509. ULONG TheItem;
  510.  
  511. struct IntuiText MenuItemText = {
  512.    BLUP,         /* Front Pen */
  513.    WHTP,         /* Back pen */
  514.    JAM2,         /* Draw Mode */
  515.    0,            /* Left Edge */
  516.    0,            /* Top */
  517.    &TestFont,    /* pointer to TextFont */
  518.    "About SpeechToy...", /* text */
  519.    NULL          /* next */
  520. };
  521. struct MenuItem MyMenuItem = {
  522.    NULL,                /* pointer to next item */
  523.    0,                   /* left */
  524.    0,                   /* top */
  525.    150,                 /* width */
  526.    8,                   /* height */
  527.    ITEMTEXT | ITEMENABLED | HIGHCOMP,  /* flags */
  528.    0,                   /* no mutual exclude */
  529.    (APTR)&MenuItemText, /* Render */
  530.    NULL,                /* pointer to alternate image */
  531.    NULL,                /* Command "amiga" char */
  532.    NULL,                /* Sub Item */
  533.    MENUNULL             /* nextselect */
  534. };
  535.  
  536. struct Menu MyMenu = {
  537.    NULL,          /* pointer to next menu */
  538.    0,0,150,0,     /* left,0,Width,0 */
  539.    MENUENABLED,   /* flags */
  540.    "SpeachToy Menu",   /* menu name */
  541.    &MyMenuItem    /* First Item in list */
  542. };
  543.  
  544. struct IntuiText ReqText1 = {
  545.    BLUP,         /* Front Pen */
  546.    WHTP,         /* Back pen */
  547.    JAM2,         /* Draw Mode */
  548.    5,            /* Left Edge */
  549.    23,           /* Top */
  550.    &TestFont,    /* pointer to TextFont */
  551.    "Version 1.1  21 Dec, 1985     Version 1.2  06 Apr, 1994",  /* text */
  552.    NULL          /* next */
  553. };
  554. struct IntuiText ReqText2 = {
  555.    BLUP,         /* Front Pen */
  556.    WHTP,         /* Back pen */
  557.    JAM2,         /* Draw Mode */
  558.    5,            /* Left Edge */
  559.    13,           /* Top */
  560.    &TestFont,    /* pointer to TextFont */
  561.    "                  Freeware - Public Domain ", /* text */
  562.    &ReqText1     /* next */
  563. };
  564. struct IntuiText ReqText3 = {
  565.    BLUP,         /* Front Pen */
  566.    WHTP,         /* Back pen */
  567.    JAM2,         /* Draw Mode */
  568.    5,            /* Left Edge */
  569.    3,            /* Top */
  570.    &TestFont,    /* pointer to TextFont */
  571.    "Written by David M Lucas           Updated by Mike Haas", /* text */
  572.    &ReqText2     /* next */
  573. };
  574.  
  575. struct IntuiText OKIText = {
  576.    BLUP, WHTP, /* FrontPen, BackPen */
  577.    JAM2,       /* DrawMode */
  578.    6, 3,       /* LeftEdge, TopEdge (relative to gadget) */
  579.    &TestFont,  /* pointer to TextFont */
  580.    "OK",       /* pointer to Text */
  581.    NULL        /* no pointer to NextText */
  582. };
  583.  
  584. struct Requester *AboutRequester;
  585.  
  586. USHORT autoret;
  587. struct Window *ControlWindow = NULL;
  588. struct Window *FaceWindow = NULL;
  589. struct IntuiMessage *MyIntuiMessage;
  590. struct NewWindow NewControlWindow = {
  591.    00, 11,                    /* start LeftEdge, TopEdge */
  592.    CONTWINDW, CONTWINDH,      /* start Width, Height */
  593.    -1, -1,                    /* DetailPen, BlockPen */
  594.    GADGETUP | CLOSEWINDOW | MENUPICK,  /* IDCMP FLAGS */
  595.    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
  596.    | GIMMEZEROZERO | ACTIVATE,/* Flags (can be NULL) */
  597.    &Props[NUMPROPS-1],        /* Pointer to FirstGadget */
  598.    NULL,                    /* no pointer to first CheckMark */
  599.    "SpeechToy",               /* Title (can be NULL) */
  600.    NULL,                      /* no Pointer to Screen */
  601.    NULL,                      /* no Pointer to BitMap */
  602.    20, 20,                    /* Min/max  Sizable to (w/h) */
  603.    CONTWINDW, CONTWINDH,      /* These aint used, can't size */
  604.    WBENCHSCREEN         /* Type of screen window appears in */
  605. };
  606.  
  607. struct NewWindow NewFaceWindow = {
  608.    CONTWINDW, 11,             /* start LeftEdge, TopEdge */
  609.    FACEWINDW * 2, FACEWINDH,  /* start Width, Height */
  610.    -1, -1,                    /* DetailPen, BlockPen */
  611.    SIZEVERIFY | NEWSIZE | MENUPICK,      /* IDCMP FLAGS */
  612.    /* Flags (can be NULL) */
  613.    WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING
  614.     | SIZEBBOTTOM | GIMMEZEROZERO | ACTIVATE,
  615.    NULL,                /* no Pointer to FirstGadget */
  616.    NULL,                /* no Pointer to first CheckMark */
  617.    "Face",              /* Title */
  618.    NULL,                /* no Pointer to Screen */
  619.    NULL,                /* no Pointer to BitMap */
  620.    FACEWINDW, FACEWINDH,/* Minimum sizeable to */
  621.    640, 200,            /* Maximum sizeable to */
  622.    WBENCHSCREEN         /* Type of screen window appears in */
  623. };
  624.  
  625. USHORT FemaleIData[] = {
  626. /*   ----    -  These nibbles matter to image. */
  627.    0x0000, 0x0000,
  628.    0x00F0, 0x0000,
  629.    0x0198, 0x0000,
  630.    0x030C, 0x0000,
  631.    0x0198, 0x0000,
  632.    0x00F0, 0x0000,
  633.    0x0060, 0x0000,
  634.    0x01F8, 0x0000,
  635.    0x0060, 0x0000,
  636.    0x0000, 0x0000
  637. };
  638.  
  639. USHORT MaleIData[] = {
  640. /*   ----    -   These nibbles matter to image. */
  641.    0x0000, 0x0000,
  642.    0x003E, 0x0000,
  643.    0x000E, 0x0000,
  644.    0x0036, 0x0000,
  645.    0x01E0, 0x0000,
  646.    0x0330, 0x0000,
  647.    0x0618, 0x0000,
  648.    0x0330, 0x0000,
  649.    0x01E0, 0x0000,
  650.    0x0000, 0x0000
  651. };
  652. USHORT HumanIData[] = {
  653. /*   ----   ----   --   These nibbles matter to image. */
  654.    0x0000,0x0000,0x0000,
  655.    0x0000,0x0000,0x0000,
  656.    0x0000,0x0000,0x0000,
  657.    0x0000,0x0000,0x0000,
  658.    0x0007,0x9E00,0x0000,
  659.    0x0001,0x8600,0x0000,
  660.    0x0000,0x0000,0x0000,
  661.    0x0000,0x0000,0x0000,
  662.    0x0000,0x2000,0x0000,
  663.    0x0000,0x1000,0x0000,
  664.    0x0000,0x0800,0x0000,
  665.    0x0000,0x7C00,0x0000,
  666.    0x0000,0x0000,0x0000,
  667.    0x0000,0x0000,0x0000,
  668.    0x0000,0x0000,0x0000,
  669.    0x0000,0x7800,0x0000,
  670.    0x0000,0x0000,0x0000,
  671.    0x0000,0x0000,0x0000,
  672.    0x0000,0x0000,0x0000,
  673.    0x0000,0x0000,0x0000
  674. };
  675. USHORT RobotIData[] = {
  676. /*   ----   ----   --   These nibbles matter to image. */
  677.    0x0000,0x0000,0x0000,
  678.    0x0000,0x0000,0x0000,
  679.    0x0000,0x0000,0x0000,
  680.    0x0000,0x0000,0x0000,
  681.    0x0007,0x9E00,0x0000,
  682.    0x0004,0x9200,0x0000,
  683.    0x0007,0x9E00,0x0000,
  684.    0x0000,0x0000,0x0000,
  685.    0x0000,0x0000,0x0000,
  686.    0x0000,0x0000,0x0000,
  687.    0x0000,0x0000,0x0000,
  688.    0x0000,0x0000,0x0000,
  689.    0x0000,0x0000,0x0000,
  690.    0x0001,0xF800,0x0000,
  691.    0x0001,0x0800,0x0000,
  692.    0x0001,0xF800,0x0000,
  693.    0x0000,0x0000,0x0000,
  694.    0x0000,0x0000,0x0000,
  695.    0x0000,0x0000,0x0000,
  696.    0x0000,0x0000,0x0000
  697. };
  698. USHORT FaceIData[] = {
  699. /*   ----   ----   --   These nibbles matter to image. */
  700.    0x0000,0x0000,0x0000,
  701.    0x0000,0x0000,0x0000,
  702.    0x0000,0x0000,0x0000,
  703.    0x0000,0x0000,0x0000,
  704.    0x0000,0x0000,0x0000,
  705.    0x0000,0x0000,0x0000,
  706.    0x0000,0x0000,0x0000,
  707.    0x0000,0x0000,0x0000,
  708.    0x0000,0x0000,0x0000,
  709.    0x0000,0x0000,0x0000
  710. };
  711. USHORT StopIData[] = {
  712. /*   ----   ----   --   These nibbles matter to image. */
  713.    0x0000,0x0000,0x0000,
  714.    0x0000,0x0000,0x0000,
  715.    0x0000,0x0000,0x0000,
  716.    0x0000,0x0000,0x0000,
  717.    0x0000,0x0000,0x0000,
  718.    0x0000,0x0000,0x0000,
  719.    0x0000,0x0000,0x0000,
  720.    0x0000,0x0000,0x0000,
  721.    0x0000,0x0000,0x0000,
  722.    0x0000,0x0000,0x0000
  723. };
  724. USHORT *FemaleIData_chip = 0;
  725. USHORT *MaleIData_chip = 0;
  726. USHORT *HumanIData_chip = 0;
  727. USHORT *RobotIData_chip = 0;
  728. USHORT *FaceIData_chip = 0;
  729. USHORT *StopIData_chip = 0;
  730.  
  731. /** start of code ***************************/
  732. main()
  733. {
  734.    ULONG Signals;        /* Wait() tells me which to look at */
  735.    ULONG MIClass;        /* Save quickly, ReplyMsg() asap */
  736.    USHORT MICode;        /* These hold my needed information */
  737.    APTR MIAddress;
  738.    ULONG fwval;
  739.  
  740.    /* let MyCleanup know these signals not allocated yet */
  741.    talk_port.mp_SigBit = -1;
  742.    read_port.mp_SigBit = -1;
  743.  
  744.    /* Open those libraries that the program uses directly */
  745.    
  746.    if ((IntuitionBase = (struct IntuitionBase *)
  747.     OpenLibrary("intuition.library", LIBRARY_MINIMUM)) == 0) { /*00001*/
  748. #ifdef DEBUG
  749.       printf("Can't open the intuition library\n");
  750. #endif
  751.       MyCleanup();
  752.       exit(FALSE);
  753.    }
  754.  
  755.    if ((GfxBase = (struct GfxBase *)
  756.     OpenLibrary("graphics.library", LIBRARY_MINIMUM /*00001*/)) == 0) {
  757. #ifdef DEBUG
  758.       printf("Can't open the graphics library\n");
  759. #endif
  760.       MyCleanup();
  761.       exit(FALSE);
  762.    }
  763.  
  764.    if ((TranslatorBase = (struct Library *)
  765.     OpenLibrary("translator.library", LIBRARY_MINIMUM /*00001*/)) == 0) {
  766. #ifdef DEBUG
  767.       printf("Can't open the translator library\n");
  768. #endif
  769.       MyCleanup();
  770.       exit(FALSE);
  771.    }
  772.  
  773.    /* Open the device */
  774.    if ((NarratorOpenError = OpenDevice("narrator.device", 0,
  775.     &voice_io, 0)) != 0) {
  776. #ifdef DEBUG
  777.       printf("Can't open the narrator device\n");
  778. #endif
  779.       MyCleanup();
  780.       exit(FALSE);
  781.    }
  782.    
  783.    /*00004 - part of workaround for 1.3/2.0 incompatibility*/
  784.    NarratorVersion = voice_io.message.io_Device->dd_Library.lib_version;
  785.    
  786.    /* This is where the proportional gadgets are set up, using
  787.     * the templates that were declared staticly.
  788.     */
  789.    for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
  790.       PTexts[PropCount] = TPropText;
  791.       Props[PropCount] = TPropGadget;
  792.       PInfos[PropCount] = TPropInfo;
  793.       Props[PropCount].GadgetText = (struct IntuiText *)
  794.        &PTexts[PropCount];
  795.       Props[PropCount].GadgetRender = (APTR)
  796.        &PImages[PropCount];
  797.       Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
  798.       switch (PropCount) {
  799.       case 0:
  800.          PTexts[PropCount].IText = "Sample Freq:";
  801.          if (DEFFREQ == MAXFREQ)
  802.             PInfos[PropCount].HorizPot = 65535;
  803.          else
  804.             PInfos[PropCount].HorizPot = ((DEFFREQ - MINFREQ)
  805.              << 16) / (MAXFREQ - MINFREQ);
  806.          break;
  807.       case 1:
  808.          PTexts[PropCount].IText = "Rate:";
  809.          Props[PropCount].TopEdge += 22;
  810.          Props[PropCount].NextGadget = &Props[PropCount-1];
  811.          if (DEFRATE == MAXRATE)
  812.             PInfos[PropCount].HorizPot = 65535;
  813.          else
  814.             PInfos[PropCount].HorizPot = ((DEFRATE - MINRATE)
  815.              << 16) / (MAXRATE - MINRATE);
  816.          break;
  817.       case 2:
  818.          PTexts[PropCount].IText = "Pitch:";
  819.          Props[PropCount].LeftEdge += 183;
  820.          Props[PropCount].NextGadget = &Props[PropCount-1];
  821.          if (DEFPITCH == MAXPITCH)
  822.             PInfos[PropCount].HorizPot = 65535;
  823.          else
  824.             PInfos[PropCount].HorizPot = ((DEFPITCH-MINPITCH)
  825.              << 16) / (MAXPITCH - MINPITCH);
  826.          break;
  827.       case 3:
  828.          PTexts[PropCount].IText = "Volume:";
  829.          Props[PropCount].TopEdge += 22;
  830.          Props[PropCount].LeftEdge += 183;
  831.          Props[PropCount].NextGadget = &Props[PropCount-1];
  832.          if (DEFVOL == MAXVOL)
  833.             PInfos[PropCount].HorizPot = 65535;
  834.          else
  835.             PInfos[PropCount].HorizPot = ((DEFVOL - MINVOL)
  836.              << 16) / (MAXVOL - MINVOL);
  837.          break;
  838.       }
  839.    }
  840.  
  841.    /* Now allocate memory accessable by the chips for images */
  842.    if (InitImages() != TRUE) {
  843. #ifdef DEBUG
  844.       printf("Couldn't Allocate Images in chip memory.\n");
  845. #endif
  846.       MyCleanup();
  847.       exit(FALSE);
  848.    }
  849.  
  850.    /* Set up the write port, allocate the signal, */
  851.    /* and the message */
  852.    talk_port.mp_Node.ln_Type = NT_MSGPORT;
  853.    talk_port.mp_Flags = 0;
  854.    if ((talk_port.mp_SigBit = AllocSignal(-1)) == -1) {
  855. #ifdef DEBUG
  856.       printf("Couldn't Allocate talk Signal bit\n");
  857. #endif
  858.       MyCleanup();
  859.       exit(FALSE);
  860.    }
  861.    talk_port.mp_SigTask = (void *) FindTask((char *)    /*00002*/
  862.     NULL);
  863.    NewList(&talk_port.mp_MsgList);
  864.  
  865.    /* Set up the read port, allocate the signal, */
  866.    /*  and the message */
  867.    read_port.mp_Node.ln_Type = NT_MSGPORT;
  868.    read_port.mp_Flags = 0;
  869.    if ((read_port.mp_SigBit = AllocSignal(-1)) == -1) {
  870. #ifdef DEBUG
  871.       printf("Couldn't Allocate read Signal bit\n");
  872. #endif
  873.       MyCleanup();
  874.       exit(FALSE);
  875.    }
  876.    read_port.mp_SigTask = (void *)    /*00002*/
  877.     FindTask((char *) NULL);
  878.    NewList(&read_port.mp_MsgList);
  879.  
  880.    /* Set up the write channel information */
  881.    voice_io.ch_masks = (audio_chan);
  882.    voice_io.nm_masks = sizeof(audio_chan);
  883.    voice_io.mouths = 0;
  884.    voice_io.message.io_Message.mn_ReplyPort = &talk_port;
  885.    voice_io.message.io_Command = CMD_WRITE;
  886.    voice_io.message.io_Offset = 0;
  887.    voice_io.message.io_Data = (APTR)PhonBuffer;
  888.    voice_io.message.io_Message.mn_Length = sizeof(voice_io);
  889.  
  890.   /* Set up the read channel information */
  891.    mouth_io.voice = voice_io;
  892.  
  893. /*00004 - part of workaround for 1.3/2.0 incompatibility*/
  894.    if (NarratorVersion >= 37)  {
  895.       mouth_io.width = 0;
  896.       mouth_io.height = 0;
  897.    }
  898.    else  {
  899.       mouth_io.voice.F0enthusiasm = 0;
  900.       mouth_io.voice.F0perturb = 0;
  901.    }
  902.    
  903.    mouth_io.voice.message.io_Message.mn_ReplyPort = &read_port;
  904.    mouth_io.voice.message.io_Command = CMD_READ;
  905.    mouth_io.voice.message.io_Error = 0;
  906.    if (FaceWindow == NULL) {
  907.       if ((ControlWindow = (struct Window *)OpenWindow
  908.        (&NewControlWindow)) == NULL) {
  909. #ifdef DEBUG
  910.          printf("Couldn't open the control window.\n");
  911. #endif
  912.          MyCleanup();
  913.          exit(FALSE);
  914.       }
  915.    }
  916.  
  917.    /* fill background of window */
  918.    SetAPen(ControlWindow->RPort, BLKP);
  919.    RectFill(ControlWindow->RPort,0,0,
  920.     ControlWindow->GZZWidth, ControlWindow->GZZHeight);
  921.    RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
  922.  
  923.    SetMenuStrip(ControlWindow, &MyMenu);
  924.  
  925. /* !!! Ah, But what if FaceWindow's not been opened? */
  926.    for (;;) {  /* ever wait for a signal and process it */
  927.       /* wait lets the rest of the system run, */
  928.       /* this program sleeps */
  929.       
  930.       fwval = 0;        /*00003*/
  931.       if (FaceWindow != NULL)  {
  932.          fwval = (ULONG)1 << FaceWindow->UserPort->mp_SigBit;
  933.       }
  934.          
  935.       Signals = Wait((1 << ControlWindow->UserPort->mp_SigBit)
  936. | (fwval)
  937. | (1 << voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)
  938. | (1 <<
  939.    mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit));
  940.       /* now check to see to what we owe the intrusion */
  941.  
  942.       if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  943.          /* Process the Intuition message */
  944.          while (MyIntuiMessage=(struct IntuiMessage *)
  945.                       GetMsg(ControlWindow->UserPort)) {
  946.             /* Get all the needed info and give message back */
  947.             MIClass = MyIntuiMessage->Class;
  948.             MICode = MyIntuiMessage->Code;
  949.             MIAddress = MyIntuiMessage->IAddress;
  950.             ReplyMsg(MyIntuiMessage);
  951.             /* Now, what was it you wanted? */
  952.             switch (MIClass) {
  953.                case MENUPICK:
  954.                   menumessage(MICode, ControlWindow);
  955.                   break;
  956.                case GADGETUP:         /* reply, then process */
  957.                   gadgetmessage(MIAddress, ControlWindow);
  958.                   break;
  959.                case CLOSEWINDOW:       /* bye! */
  960.                   while (MyIntuiMessage = (struct
  961.                    IntuiMessage *) GetMsg(
  962.                    ControlWindow->UserPort))
  963.                     ReplyMsg(MyIntuiMessage);
  964.                   MyCleanup();
  965.                   exit(TRUE);
  966.                   break;
  967.                default:
  968. #ifdef DEBUG
  969.                   printf("Unhandled Message Received.\n");
  970. #endif
  971.                   break;
  972.             }  /* switch */
  973.          } /* while */
  974.       } /* if */
  975.  
  976.  
  977.       if (FaceWindow != NULL)  {    /*00003*/
  978.          /* Woken by intuition for FaceWindow*/
  979.          if (Signals & (1 << FaceWindow->UserPort->mp_SigBit)) {
  980.             /* Process the Intuition message */
  981.             while (MyIntuiMessage=(struct IntuiMessage *)
  982.              GetMsg(FaceWindow->UserPort)) {
  983.                switch (MyIntuiMessage->Class) {
  984.                   case SIZEVERIFY:
  985.                      ReplyMsg(MyIntuiMessage);
  986.                      break;
  987.                   case MENUPICK:
  988.                      menumessage(MyIntuiMessage->Code,FaceWindow);
  989.                      ReplyMsg(MyIntuiMessage);
  990.                      break;
  991.                   case NEWSIZE:  /* Don't reply until processed */
  992.                      DrawFace();
  993.                      ReplyMsg(MyIntuiMessage);
  994.                      break;
  995.                   default:
  996. #ifdef DEBUG
  997.                      printf("Unhandled Message Received.\n");
  998. #endif
  999.                      ReplyMsg(MyIntuiMessage);
  1000.                      break;
  1001.                }  /* switch */
  1002.             } /* while */
  1003.          } /* if */
  1004.       } /* if */
  1005.  
  1006.       /* A voice SendIO (Write) has completed */
  1007.       if (Signals & (1 <<
  1008.        voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1009.          /* Was it Sucessful? filter out the abort error */
  1010.          if (voice_io.message.io_Error == -2)
  1011.             voice_io.message.io_Error = 0;
  1012.          if (voice_io.message.io_Error != 0) {
  1013. #ifdef DEBUG
  1014.             printf("Narrator won't. (%ld)\n",
  1015.              voice_io.message.io_Error);
  1016. #endif
  1017.             /* flash this screen */
  1018.             DisplayBeep(ControlWindow->WScreen);
  1019.             /* let user see where phoneme string was bad. */
  1020.             i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1021.             /* move the cursor to the error char */
  1022.             PhonInfo.BufferPos = voice_io.message.io_Actual -1;
  1023.             /* assure cursor (error point) is shown in gad. */
  1024.             /* within 29 (number of chars shown) of front */
  1025.             if (voice_io.message.io_Actual < 29)
  1026.                PhonInfo.DispPos = 0;
  1027.             /* within 29 of end */
  1028.             else if ((voice_io.message.io_Length -
  1029.                       voice_io.message.io_Actual) < 29)
  1030.                PhonInfo.DispPos = voice_io.message.io_Length
  1031.                                   - 29;
  1032.             else
  1033.                PhonInfo.DispPos = voice_io.message.io_Actual
  1034.                                   - 15;
  1035.             AddGadget(ControlWindow, &PhonStrGadget, i);
  1036.             RefreshGadgets(&PhonStrGadget, ControlWindow,
  1037.              NULL);
  1038.             voice_io.message.io_Error = 0;
  1039.          }
  1040. /*       SpeakGadget.Flags ^= GADGDISABLED;
  1041.          FaceGadget.Flags ^= GADGDISABLED;
  1042. */
  1043.          OnGadget(&SpeakGadget, ControlWindow, NULL);
  1044.          OnGadget(&FaceGadget,  ControlWindow, NULL);
  1045.       }
  1046.  
  1047.       /* A mouth DoIO (Read) has completed */
  1048.       if (Signals & (1 <<
  1049.   mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1050.          UBYTE  width, height;
  1051.          
  1052. /*00004 - part of workaround for 1.3/2.0 incompatibility*/
  1053.          if (NarratorVersion >= 37)  {
  1054.             width  = mouth_io.width;
  1055.             height = mouth_io.height;
  1056.          }
  1057.          else  {
  1058.             width  = mouth_io.voice.F0enthusiasm;
  1059.             height = mouth_io.voice.F0perturb;
  1060.          }
  1061.  
  1062.          WaitBOVP(&FaceWindow->WScreen->ViewPort);
  1063.          SetAPen(FaceWindow->RPort, WHTP);
  1064.          RectFill(FaceWindow->RPort, 0, EyesBottom,
  1065.           FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1066.          if (MouthWMult == 0)
  1067.             LipWidth = width >> 1;             /*00004*/
  1068.          else
  1069.             LipWidth = width * MouthWMult;     /*00004*/
  1070.          if (MouthHMult == 0)
  1071.             LipHeight = height >> 1;           /*00004*/
  1072.          else
  1073.             LipHeight = height * (MouthHMult); /*00004*/
  1074.             
  1075.          SetAPen(FaceWindow->RPort, REDP);
  1076.          Move(FaceWindow->RPort,
  1077.           XMouthCenter - LipWidth, YMouthCenter);
  1078.          Draw(FaceWindow->RPort,
  1079.           XMouthCenter, YMouthCenter - LipHeight);
  1080.          Draw(FaceWindow->RPort,
  1081.           XMouthCenter + LipWidth, YMouthCenter);
  1082.          Draw(FaceWindow->RPort,
  1083.           XMouthCenter, YMouthCenter + LipHeight);
  1084.          Draw(FaceWindow->RPort,
  1085.           XMouthCenter - LipWidth, YMouthCenter);
  1086.          /* the narrator will give an error when the */
  1087.          /* write has completed and I've tried to read */
  1088.          /* so I stop trying when that happens */
  1089.          if (mouth_io.voice.message.io_Error == 0)
  1090.             SendIO(&mouth_io);
  1091.       }
  1092.    }  /* for */
  1093. }  /* main */
  1094.  
  1095. /* a MENUPICK has been received, this
  1096.  * routine takes the appropriate action
  1097.  */
  1098. menumessage(code, w)
  1099. USHORT code;
  1100. struct Window *w;
  1101. {
  1102.    switch (MENUNUM(code)) {
  1103.       case 0:
  1104.          switch (ITEMNUM(code)) {
  1105.             case 0:
  1106.                AutoRequest(w, &ReqText3, NULL,
  1107.                            &OKIText, 0, 0, 526, 47);
  1108.                break;
  1109.          }
  1110.       break;
  1111.    }
  1112. }
  1113.  
  1114. /* a GADGETUP has been received, this
  1115.  * routine takes the appropriate action
  1116.  */
  1117. gadgetmessage(address, w)
  1118. APTR address;
  1119. struct Window *w;
  1120. {
  1121.    USHORT i;
  1122.    long PropRange;
  1123.    if (address == (APTR)&ModeGadget) {
  1124.       if (ModeGadget.Flags & SELECTED)
  1125.          voice_io.mode = ROBOTICF0;
  1126.       else
  1127.          voice_io.mode = NATURALF0;
  1128.    }
  1129.    else if (address == (APTR)&FaceGadget) {
  1130.       /* tell the write that reads will be forthcomming */
  1131.       if (FaceGadget.Flags & SELECTED) {
  1132.          voice_io.mouths = 1;
  1133.          if ((FaceWindow = (struct Window *)
  1134.           OpenWindow(&NewFaceWindow)) == NULL) {
  1135. #ifdef DEBUG
  1136.             printf("Couldn't open the face window.\n");
  1137. #endif
  1138.             MyCleanup();
  1139.             exit(FALSE);
  1140.          }
  1141.          SetMenuStrip(FaceWindow, &MyMenu);
  1142.          DrawFace();
  1143.       }
  1144.       else { /* FaceGadget de-SELECTed */
  1145.          voice_io.mouths = 0;
  1146.          NewFaceWindow.LeftEdge = FaceWindow->LeftEdge;
  1147.          NewFaceWindow.TopEdge = FaceWindow->TopEdge;
  1148.          NewFaceWindow.Width = FaceWindow->Width;
  1149.          NewFaceWindow.Height = FaceWindow->Height;
  1150.          CloseWindow(FaceWindow);
  1151.          FaceWindow = NULL;
  1152.       }
  1153.    }
  1154.    else if (address == (APTR)&StopGadget) {
  1155.       AbortIO(&voice_io);
  1156.       voice_io.message.io_Error = 0;
  1157.       mouth_io.voice.message.io_Error = 0;
  1158.    }
  1159.    /* Since this program changes a flag that intuition expects
  1160.     * only the user to change (SELECTED bit), this program has
  1161.     * to remove, then change, then add this gadget. Then by
  1162.     * passing the address of this gadget to RefreshGadgets(),
  1163.     * only the gadgets from here to the start of the list will
  1164.     * be refreshed, which minimizes the visible flash that
  1165.     * RefreshGadgets() can introduce.
  1166.     * If one of the two gadgets (female/male) is hit, toggle
  1167.     * the selection of the other gadget (since the gadget hit
  1168.     * was toggled by intuition when it was hit).
  1169.     */
  1170.    else if (address == (APTR)&FemaleGadget) {
  1171.       if (FemaleGadget.Flags & SELECTED)
  1172.       voice_io.sex = FEMALE;
  1173.       else
  1174.       voice_io.sex = MALE;
  1175.       i = RemoveGadget(ControlWindow, &MaleGadget);
  1176.       MaleGadget.Flags ^= SELECTED;
  1177.       AddGadget(ControlWindow, &MaleGadget, i);
  1178.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1179.    }
  1180.    else if (address == (APTR)&MaleGadget) {
  1181.       if (MaleGadget.Flags & SELECTED)
  1182.       voice_io.sex = MALE;
  1183.       else
  1184.       voice_io.sex = FEMALE;
  1185.       i = RemoveGadget(ControlWindow, &FemaleGadget);
  1186.       FemaleGadget.Flags ^= SELECTED;
  1187.       AddGadget(ControlWindow, &FemaleGadget, i);
  1188.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1189.    }
  1190.    /* Since the program changes the contents of the string
  1191.     * gadgets' buffer and it's size, which is something else
  1192.     * intuition doesn't expect a program (as opposed to the
  1193.     * user) to do. The program must remove, then change, then
  1194.     * add this gadget, and then by passing the address of this
  1195.     * gadget to RefreshGadgets(), only the gadgets from here
  1196.     * to the start of the list will be refreshed, which
  1197.     * minimizes the visible flash that RefreshGadgets() can
  1198.     * introduce.
  1199.     */
  1200.    else if (address == (APTR)&TranslateGadget) {
  1201.       i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1202.       if ((TranslatorError = Translate((APTR)EnglBuffer,
  1203.        EnglInfo.NumChars, (APTR)PhonBuffer, PhonInfo.MaxChars))
  1204.        != 0) {
  1205. #ifdef DEBUG
  1206.          printf("Translator won't. (%lx)\n",TranslatorError);
  1207. #endif
  1208.          /* flash this screen */
  1209.          DisplayBeep(ControlWindow->WScreen);
  1210.       }
  1211.       /* Hey! NumChars includes the terminating NULL. */
  1212.       /* This must be done. */
  1213.       PhonInfo.NumChars = voice_io.message.io_Length + 1;
  1214.       if (PhonInfo.DispPos > voice_io.message.io_Length)
  1215.           PhonInfo.DispPos = voice_io.message.io_Length;
  1216.       AddGadget(ControlWindow, &PhonStrGadget, i);
  1217.       RefreshGadgets(&PhonStrGadget, ControlWindow, NULL);
  1218.    }
  1219.    else if (address == (APTR)&SpeakGadget) {
  1220. /*    SpeakGadget.Flags ^= GADGDISABLED;
  1221.       FaceGadget.Flags ^= GADGDISABLED;
  1222. */
  1223.       OffGadget(&SpeakGadget, ControlWindow, NULL);
  1224.       OffGadget(&FaceGadget,  ControlWindow, NULL);
  1225.  
  1226.       voice_io.message.io_Length = strlen(PhonBuffer);
  1227.       SendIO(&voice_io);
  1228.       if (voice_io.mouths == 1) {
  1229.          mouth_io.voice.message.io_Error = 0;
  1230.          SendIO(&mouth_io);
  1231.       }
  1232.    }
  1233.    else if (address == (APTR)&EnglStrGadget);  /* do nothing */
  1234.    else if (address == (APTR)&PhonStrGadget);  /* do nothing */
  1235.    else if (address == (APTR)&Props[0]) {
  1236.       PropRange = RNGFREQ;
  1237.       voice_io.sampfreq = (( (PInfos[0].HorizPot >> 1)
  1238.        * PropRange) >> 15) + MINFREQ;
  1239. #ifdef DEBUG
  1240.       printf("Freq. = %ld\n", voice_io.sampfreq);
  1241. #endif
  1242.    }
  1243.    else if (address == (APTR)&Props[1]) {
  1244.       PropRange = RNGRATE;
  1245.       voice_io.rate = (((PInfos[1].HorizPot >> 1)
  1246.        * PropRange) >> 15) + MINRATE;
  1247. #ifdef DEBUG
  1248.       printf("Rate  = %ld\n", voice_io.rate);
  1249. #endif
  1250.    }
  1251.    else if (address == (APTR)&Props[2]) {
  1252.       PropRange = RNGPITCH;
  1253.       voice_io.pitch = (((PInfos[2].HorizPot >> 1)
  1254.        * PropRange) >> 15) + MINPITCH;
  1255. #ifdef DEBUG
  1256.       printf("Pitch = %ld\n", voice_io.pitch);
  1257. #endif
  1258.    }
  1259.    else if (address == (APTR)&Props[3]) {
  1260.       PropRange = RNGVOL;
  1261.       voice_io.volume = (((PInfos[3].HorizPot >> 1)
  1262.        * PropRange) >> 15) + MINVOL;
  1263. #ifdef DEBUG
  1264.       printf("Vol.  = %ld\n", voice_io.volume);
  1265. #endif
  1266.    }
  1267. #ifdef DEBUG
  1268.    else printf("Unhandled gadget up received!\n");
  1269. #endif
  1270. }
  1271.  
  1272. /* This calculates variables used to draw the mouth
  1273.  * and eyes, as well as redrawing the face.
  1274.  * Proportionality makes it very wierd, but it's
  1275.  * wierder if you don't use a GimmeZeroZero window
  1276.  * and GZZWidth/GZZHeight.
  1277.  */
  1278. DrawFace() {
  1279.    XMouthCenter =  FaceWindow->GZZWidth >> 1;
  1280.    /* set left edge of left eye */
  1281.    EyesLeft = FaceWindow->GZZWidth >> 2;
  1282.    /* multiplier for mouth width */
  1283.    MouthWMult = FaceWindow->GZZWidth >> 6;
  1284.  
  1285.    EyesTop = (FaceWindow->GZZHeight >> 2)
  1286.     - (FaceWindow->GZZHeight >> 4);
  1287.    EyesBottom = EyesTop + (FaceWindow->GZZHeight >> 3) + 1;
  1288.    yaw = FaceWindow->GZZHeight - EyesBottom;
  1289.    YMouthCenter = ((yaw >> 1) + EyesBottom);
  1290.    MouthHMult = yaw >> 5;
  1291.  
  1292.    /* Set pen to White */
  1293.    SetAPen(FaceWindow->RPort, WHTP);
  1294.    RectFill(FaceWindow->RPort, 0, 0,
  1295.     FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1296.  
  1297.    /* Set pen to Blue */
  1298.    SetAPen(FaceWindow->RPort, BLUP);
  1299.    RectFill(FaceWindow->RPort,
  1300.     EyesLeft, EyesTop,
  1301.     EyesLeft + (FaceWindow->GZZWidth >> 3),
  1302.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1303.    RectFill(FaceWindow->RPort,
  1304.     (FaceWindow->GZZWidth >> 1)
  1305.     + (FaceWindow->GZZWidth >> 3),
  1306.     EyesTop,
  1307.     (FaceWindow->GZZWidth >> 1)
  1308.      + (FaceWindow->GZZWidth >> 3) /* two >> 3, not one >> 2 */
  1309.      + (FaceWindow->GZZWidth >> 3),/* so eyes are same width */
  1310.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1311.  
  1312.     SetAPen(FaceWindow->RPort, REDP);  /* Set pen to Red */
  1313.     Move(FaceWindow->RPort,
  1314.      XMouthCenter - (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1315.     Draw(FaceWindow->RPort,
  1316.      XMouthCenter + (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1317.  
  1318. }
  1319.  
  1320. /* Deallocate any memory, and close all of the
  1321.  * windows/screens/devices/libraries in reverse order to
  1322.  * make things work smoothly. And be sure to check
  1323.  * that the open/allocation was successful before
  1324.  * closing/deallocating.
  1325.  */
  1326. MyCleanup()
  1327. {
  1328.    if (read_port.mp_SigBit != -1)
  1329.       FreeSignal(read_port.mp_SigBit);
  1330.    if (talk_port.mp_SigBit != -1)
  1331.       FreeSignal(talk_port.mp_SigBit);
  1332.    if (FaceWindow != NULL)
  1333.       CloseWindow(FaceWindow);
  1334.    if (ControlWindow != NULL)
  1335.       CloseWindow(ControlWindow);
  1336.    /* freeimages makes sure image allocation was successful */
  1337.    freeimages();
  1338.    if (NarratorOpenError == 0)
  1339.       CloseDevice(&voice_io);
  1340.    if (TranslatorBase != 0)
  1341.       CloseLibrary(TranslatorBase);
  1342.    if (GfxBase != 0)
  1343.       CloseLibrary(GfxBase);
  1344.    if (IntuitionBase != 0)
  1345.       CloseLibrary(IntuitionBase);
  1346.    return(0);
  1347. }
  1348.  
  1349. /* Allocate chip memory for gadget images, and set the
  1350.  * pointers in the corresponding image structures to point
  1351.  * to these images. This must be done because the program
  1352.  * could be loaded into expansion memory (off the side of
  1353.  * the box), which the custom chips cannot access.
  1354.  * And images must be in chip ram (that's memory that the
  1355.  * custom chips can access, the internal 512K).
  1356.  */
  1357. InitImages()
  1358. {
  1359.    /* the images were staticly initialized above main */
  1360.    extern USHORT *FemaleIData_chip;
  1361.    extern USHORT *MaleIData_chip;
  1362.    extern USHORT *HumanIData_chip;
  1363.    extern USHORT *RobotIData_chip;
  1364.    extern USHORT *FaceIData_chip;
  1365.    extern USHORT *StopIData_chip;
  1366.    int i;
  1367.  
  1368.    /* Allocate them all, stop and return false on failure */
  1369.    if ((FemaleIData_chip = (USHORT *)
  1370.     AllocMem(sizeof(FemaleIData),MEMF_CHIP)) == 0)
  1371.       return(FALSE);
  1372.    if ((MaleIData_chip = (USHORT *)
  1373.     AllocMem(sizeof(MaleIData),MEMF_CHIP)) == 0)
  1374.       return(FALSE);
  1375.    if ((HumanIData_chip = (USHORT *)
  1376.     AllocMem(sizeof(HumanIData),MEMF_CHIP)) == 0)
  1377.       return(FALSE);
  1378.    if ((RobotIData_chip = (USHORT *)
  1379.     AllocMem(sizeof(RobotIData),MEMF_CHIP)) == 0)
  1380.       return(FALSE);
  1381.    if ((FaceIData_chip = (USHORT *)
  1382.     AllocMem(sizeof(FaceIData),MEMF_CHIP)) == 0)
  1383.       return(FALSE);
  1384.    if ((StopIData_chip = (USHORT *)
  1385.     AllocMem(sizeof(StopIData),MEMF_CHIP)) == 0)
  1386.       return(FALSE);
  1387.  
  1388.    for (i=0; i<20; i++)
  1389.       FemaleIData_chip[i] = FemaleIData[i];
  1390.    for (i=0; i<20; i++)
  1391.       MaleIData_chip[i] = MaleIData[i];
  1392.    for (i=0; i<60; i++)
  1393.       HumanIData_chip[i] = HumanIData[i];
  1394.    for (i=0; i<60; i++)
  1395.       RobotIData_chip[i] = RobotIData[i];
  1396.    for (i=0; i<30; i++)
  1397.       FaceIData_chip[i] = FaceIData[i];
  1398.    for (i=0; i<30; i++)
  1399.       StopIData_chip[i] = StopIData[i];
  1400.  
  1401.    FemaleImage.ImageData = FemaleIData_chip;
  1402.    MaleImage.ImageData = MaleIData_chip;
  1403.    HumanImage.ImageData = HumanIData_chip;
  1404.    RobotImage.ImageData = RobotIData_chip;
  1405.    FaceImage.ImageData = FaceIData_chip;
  1406.    StopImage.ImageData = StopIData_chip;
  1407.  
  1408.    return(TRUE);
  1409. }
  1410.  
  1411. /* Deallocate the memory that was used for images,
  1412.  * See initimages for more details.
  1413.  */
  1414. freeimages()
  1415. {
  1416.    /* the images were staticly initialized above main */
  1417.    extern USHORT *FemaleIData_chip;
  1418.    extern USHORT *MaleIData_chip;
  1419.    extern USHORT *HumanIData_chip;
  1420.    extern USHORT *RobotIData_chip;
  1421.    extern USHORT *FaceIData_chip;
  1422.    extern USHORT *StopIData_chip;
  1423.  
  1424.    /* Deallocate only if the pointer is really there. */
  1425.    if (RobotIData_chip != 0)
  1426.       FreeMem(RobotIData_chip, sizeof(RobotIData));
  1427.    if (HumanIData_chip != 0)
  1428.       FreeMem(HumanIData_chip, sizeof(HumanIData));
  1429.    if (MaleIData_chip != 0)
  1430.       FreeMem(MaleIData_chip, sizeof(MaleIData));
  1431.    if (FemaleIData_chip != 0)
  1432.       FreeMem(FemaleIData_chip, sizeof(FemaleIData));
  1433.    if (FaceIData_chip != 0)
  1434.       FreeMem(FaceIData_chip, sizeof(FaceIData));
  1435.    if (StopIData_chip != 0)
  1436.       FreeMem(StopIData_chip, sizeof(StopIData));
  1437. }
  1438.